#pragma once

#ifndef EVENTENGINEADAPTER_H
#define EVENTENGINEADAPTER_H


#include "SmartTrade\SmartTradecUserApiStruct.h"
#include "BaseStrategy.h"
#include <loki\SmartPtr.h>

namespace SmartTrade{
	template<typename T,typename Event>
	struct EventMonitor{
		union{
			int Addr;
			void (T::*OnEvent)(Event* pEvent);
		};
		char* EventCode;
	};
	
	struct EventEngineAdapter{
		typedef Loki::SmartPtr<EventMonitor<EventEngineAdapter,SmartTradecQuoteInstrument> >      Ptr_QuoteMonitor;
		typedef Loki::SmartPtr<EventMonitor<EventEngineAdapter,SmartTradecTradeInstrument> >      Ptr_TradeMonitor;
		typedef Loki::SmartPtr<EventMonitor<EventEngineAdapter,SmartTradecBarInstrument> >		  Ptr_BarMonitor;
		typedef Loki::SmartPtr<EventMonitor<EventEngineAdapter,SmartTradecDepthMarketData> >	  Ptr_DepthMarketDataMonitor;
		typedef Loki::SmartPtr<EventMonitor<EventEngineAdapter,SmartTradecPairQuoteData> >		  Ptr_PairQuoteMonitor;
		typedef Loki::SmartPtr<EventMonitor<EventEngineAdapter,SmartTradecPairTradeData> >		  Ptr_PairTradeMonitor;
		typedef Loki::SmartPtr<EventMonitor<EventEngineAdapter,SmartTradecPairBarData> >		  Ptr_PairBarMonitor;
		typedef Loki::SmartPtr<EventMonitor<EventEngineAdapter,SmartTradecPairDepthMarketData> >  Ptr_PairDepthMarketDataMonitor;
		EventEngineAdapter(Ptr_StrategyMap pStrategyMap){
			
			pStrategyMap_ = pStrategyMap;

			pQuoteMon_			= NULL;
			pTradeMon_			= NULL;
			pBarMon_			= NULL;
			pDepthDataMon_		= NULL;
			pPairQuoteMon_		= NULL;		
			pPairTradeMon_		= NULL;
			pPairBarMon_		= NULL;
			pPairDepthDataMon_	= NULL;

			Start();
		}

		void Start(){
			pQuoteMon_ = new EventMonitor<EventEngineAdapter,SmartTradecQuoteInstrument>();
			pQuoteMon_->OnEvent = &EventEngineAdapter::On_Quote;
			strcpy(pQuoteMon_->EventCode , MARKET_DATA_TYPE_QUOTE);

			pTradeMon_ = new EventMonitor<EventEngineAdapter,SmartTradecTradeInstrument>();
			pTradeMon_->OnEvent = &EventEngineAdapter::On_Trade;
			strcpy(pTradeMon_->EventCode , MARKET_DATA_TYPE_TRADE);

			pBarMon_ = new EventMonitor<EventEngineAdapter,SmartTradecBarInstrument>();
			pBarMon_->OnEvent = &EventEngineAdapter::On_Bar;
			strcpy(pBarMon_->EventCode , MARKET_DATA_TYPE_CLOSEBAR);

			pDepthDataMon_ = new EventMonitor<EventEngineAdapter,SmartTradecDepthMarketData>();
			pDepthDataMon_->OnEvent = &EventEngineAdapter::On_DepthMarketData;
			strcpy(pDepthDataMon_->EventCode , MARKET_DATA_TYPE_DEPTHMARKETDATA);

			pPairQuoteMon_ = new EventMonitor<EventEngineAdapter,SmartTradecPairQuoteData>();
			pPairQuoteMon_->OnEvent = &EventEngineAdapter::On_PairQuote;
			strcpy(pPairQuoteMon_->EventCode , MARKET_DATA_TYPE_PAIRQUOTE);

			pPairTradeMon_ = new EventMonitor<EventEngineAdapter,SmartTradecPairTradeData>();
			pPairTradeMon_->OnEvent = &EventEngineAdapter::On_PairTrade;
			strcpy(pPairTradeMon_->EventCode , MARKET_DATA_TYPE_PAIRTRADE);

			pPairBarMon_ = new EventMonitor<EventEngineAdapter,SmartTradecPairBarData>();
			pPairBarMon_->OnEvent = &EventEngineAdapter::On_PairCloseBar;
			strcpy(pPairBarMon_->EventCode , MARKET_DATA_TYPE_PAIRCLOSEBAR);

			pPairDepthDataMon_ = new EventMonitor<EventEngineAdapter,SmartTradecPairDepthMarketData>();
			pPairDepthDataMon_->OnEvent = &EventEngineAdapter::On_PairDepthMarketData;
			strcpy(pPairDepthDataMon_->EventCode , MARKET_DATA_TYPE_PAIRDEPTHMARKETDATA);
		}

		void RegisterToEventEngine(){
			
			//RegisterEventMonitor(pQuoteMon_->EventCode,pQuoteMon_->Addr,this);
			//RegisterEventMonitor(pTradeMon_->EventCode,pTradeMon_->Addr,this);
			//RegisterEventMonitor(pBarMon_->EventCode,pBarMon_->Addr,this);
			//RegisterEventMonitor(pDepthDataMon_->EventCode,pDepthDataMon_->Addr,this);
			//RegisterEventMonitor(pPairQuoteMon_->EventCode,pPairQuoteMon_->Addr,this);
			//RegisterEventMonitor(pPairTradeMon_->EventCode,pPairTradeMon_->Addr,this);
			//RegisterEventMonitor(pPairBarMon_->EventCode,pPairBarMon_->Addr,this);
			//RegisterEventMonitor(pPairDepthDataMon_->EventCode,pPairDepthDataMon_->Addr,this);
		}
		
		void On_Quote(SmartTradecQuoteInstrument* pQuote){

			for(StrategyMapIterator i = pStrategyMap_->begin();i != pStrategyMap_->end(); ++i){
				i->second->On_Quote(pQuote);
			}
		}
		void On_Trade(SmartTradecTradeInstrument* pTrade){
			for(StrategyMapIterator i = pStrategyMap_->begin();i != pStrategyMap_->end(); ++i){
				i->second->On_Trade(pTrade);
			}
		}
		void On_Bar(SmartTradecBarInstrument* pBar){
			for(StrategyMapIterator i = pStrategyMap_->begin();i != pStrategyMap_->end(); ++i){
				i->second->On_Bar(pBar);
			}
		}
		void On_DepthMarketData(SmartTradecDepthMarketData* pDepthMarketData){
			for(StrategyMapIterator i = pStrategyMap_->begin();i != pStrategyMap_->end(); ++i){
				i->second->On_DepthMarketData(pDepthMarketData);
			}
		}
		void On_PairQuote(SmartTradecPairQuoteData* pPairQuote){
			for(StrategyMapIterator i = pStrategyMap_->begin();i != pStrategyMap_->end(); ++i){
				i->second->On_PairQuote(pPairQuote);
			}
		}
		void On_PairTrade(SmartTradecPairTradeData* pPairTrade){
			for(StrategyMapIterator i = pStrategyMap_->begin();i != pStrategyMap_->end(); ++i){
				i->second->On_PairTrade(pPairTrade);
			}
		}
		void On_PairCloseBar(SmartTradecPairBarData* pPairBar){
			for(StrategyMapIterator i = pStrategyMap_->begin();i != pStrategyMap_->end(); ++i){
				i->second->On_PairCloseBar(pPairBar);
			}
		}
		void On_PairDepthMarketData(SmartTradecPairDepthMarketData* pPairDepthMarketData){
			for(StrategyMapIterator i = pStrategyMap_->begin();i != pStrategyMap_->end(); ++i){
				i->second->On_PairDepthMarketData(pPairDepthMarketData);
			}
		}

	private:
		Ptr_QuoteMonitor			   pQuoteMon_;
		Ptr_TradeMonitor			   pTradeMon_;
		Ptr_BarMonitor				   pBarMon_;
		Ptr_DepthMarketDataMonitor	   pDepthDataMon_;
		Ptr_PairQuoteMonitor		   pPairQuoteMon_;
		Ptr_PairTradeMonitor		   pPairTradeMon_;
		Ptr_PairBarMonitor             pPairBarMon_;
		Ptr_PairDepthMarketDataMonitor pPairDepthDataMon_;

		Ptr_StrategyMap pStrategyMap_; 
	};
	
	typedef Loki::SmartPtr<EventEngineAdapter> Ptr_EventEngineAdapter; 
}

#endif // EVENTENGINEADAPTER_H